package liming.ai.code.v3.generator;

import liming.ai.code.v3.data.FileInfo;
import liming.ai.code.v3.data.JavaCode;
import liming.tool.file.FileRW;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;

public class HandlerCode {

    // 生成Java文件（适配FileData）
    public static boolean writeForFile(FileInfo fileData, String code) {
        try {
            FileRW.writeTextFile(fileData.getJavaFile(), code, false);
            return true;
        } catch (IOException e) {
            fileData.setException(e);
        }
        return false;
    }

    // 编译Java文件（适配FileData）
    public static boolean compileJavaFile(FileInfo fileData, JavaCode code, String encoding) {
        String outputDir = fileData.getClassRootPath();
        new File(outputDir).mkdirs();
        String cmd = code.getCmd();

        // 自动构建标准编译命令
        if(cmd == null || !cmd.startsWith("javac ")) {
            String sourcePath = fileData.getJavaRootPath();
            String classPath = outputDir;
            cmd = String.format("javac -encoding %s -d %s -sourcepath %s -cp %s %s",
                    encoding,
                    outputDir,
                    sourcePath,
                    classPath,
                    fileData.getJavaFile().getAbsolutePath());
        }

        System.out.println("编译执行命令: " + cmd);
        try {
            Process compileProcess = Runtime.getRuntime().exec(cmd);

            // 读取错误流的线程（提前消费避免进程阻塞）
            StringBuilder errorMessage = new StringBuilder();
            Thread errorThread = new Thread(() -> {
                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(compileProcess.getErrorStream(), FileRW.FileEncoding.AUTO.getValue()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        errorMessage.append(line).append("\n");
                    }
                } catch (IOException e) {
                    errorMessage.append("无法读取错误流: ").append(e.getMessage());
                }
            });
            errorThread.start();

            int exitCode = compileProcess.waitFor();
            errorThread.join();  // 确保错误流读取完成

            if (exitCode != 0) {
                throw new RuntimeException("cmd: "+cmd +"\n编译错误[" + exitCode + "]:\n" + errorMessage);
            }
            return true;
        } catch (Exception e) {
            fileData.setException(e);
            return false;
        }

    }

    // 类加载（适配FileData）
    public static Class<?> loadClass(FileInfo fileData) {
        try {
            String fullClassName = fileData.getFullClassName();
            File classDir = new File(fileData.getClassRootPath());

            URLClassLoader classLoader = new URLClassLoader(
                    new URL[]{classDir.toURI().toURL()},
                    System.class.getClassLoader()
            );

            Class<?> loadedClass = classLoader.loadClass(fullClassName);
            System.out.println("Loaded class: " + loadedClass.getName());
            return loadedClass;
        } catch (Exception e) {
            fileData.setException(e);
            return null;
        }
    }

    // 生成Markdown文档（新增功能）
    public static boolean generateMdFile(FileInfo fileData, String content) {
        try {
            FileRW.writeTextFile(fileData.getMdFile(), content, false);
            System.out.println("Generated MD: " + fileData.getMdFile().getAbsolutePath());
            return true;
        } catch (IOException e) {
            fileData.setException(e);
            return false;
        }
    }

    // 方法调用（保持通用性）
    public static Object doInvokeMethod(Class<?> targetClass,
                                      Object instance,
                                      String methodName,
                                      Object... args) throws Exception {
        Class<?>[] argTypes = Arrays.stream(args)
                .map(Object::getClass)
                .toArray(Class<?>[]::new);

        Method method = targetClass.getMethod(methodName, argTypes);

        if (instance == null && !Modifier.isStatic(method.getModifiers()))
            throw new IllegalArgumentException("调用非静态方法必须提供实例对象");

        return method.invoke(instance == null ? targetClass : instance, args);
    }
}